package edu.washington.vaccine.backend;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

/*
 * 
 * Communicates with SQL database via php query
 */

public class VaccineDB extends Activity {
	protected String URL_START = "http://www.cubist.cs.washington.edu/~bje575/index.php?";
	private static VaccineDB instance = null;
	private static boolean onlineMode = true;
		
	protected VaccineDB() {
		// Singleton pattern, exists to guard against instantiation.
	}
	
	/* Returns an instance of this singleton VaccineDB. If VaccineDB has not yet been
	 * created, a VaccineDB instance is created and returned. Otherwise an instance
	 * of the single VaccineDB is returned.
	 */
	public static VaccineDB getInstance() {
		if (instance == null) {
			instance = new VaccineDB();
		}
		return instance;
	}
	
	public void setOnlineMode(boolean on) {
		onlineMode = on;
	}
	
	public boolean isOnlineMode() {
		return onlineMode;
	}
	
	public boolean editPatient(Patient p) {
		String pid = "" + p.id;
		String fname = p.fname;
		String lname = p.lname;
		String dob = p.dob;
		String location = p.location;
		String mother = p.mother;
		String father = p.father;
		String editdate = p.editdate;
		String notes = p.notes;
		
		ArrayList<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
//		InputStream inpStream = null; // input stream to parse JSON response

		try {
			HttpClient httpClient = new DefaultHttpClient();
			String addUrl = URL_START + "request=edit&pid=" + pid + "&lname=" + lname +"&fname=" + fname + "&dob=" + dob + "&loc=" + location + "&mothname=" + mother + "&fathname=" + father + "&editdate=" + editdate  + "&notes=" + notes;
			HttpPost httpPost = new HttpPost(addUrl.replaceAll("[ ]+", "%20"));
			httpPost.setEntity(new UrlEncodedFormEntity(nvPairs));
			httpClient.execute(httpPost);
//			HttpResponse result = httpClient.execute(httpPost);
//			HttpEntity entity = result.getEntity();
//			inpStream = entity.getContent();
		} catch (IOException e) {
			return false;
		}
		
		return true;
	}
	
	public boolean addPatient(Patient p) {
		String lname = p.lname;
		String fname = p.fname;
		String dob = p.dob;
		String pid = "" + p.id;
		String location = p.location;
		String mother = p.mother;
		String father = p.father;
//		String editdate = p.editdate;
		String notes = p.notes;
		
		ArrayList<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
//		InputStream inpStream = null; // input stream to parse JSON response

		try {
			HttpClient httpClient = new DefaultHttpClient();
			String addUrl = URL_START + "request=add&pid=" + pid + "&lname=" + lname +"&fname=" + fname + "&dob=" + dob + "&loc=" + location + "&mothname=" + mother + "&fathname=" + father + "&notes=" + notes;
			HttpPost httpPost = new HttpPost(addUrl.replaceAll("[ ]+", "%20"));
			httpPost.setEntity(new UrlEncodedFormEntity(nvPairs));
			httpClient.execute(httpPost);
//			HttpResponse result = httpClient.execute(httpPost);
//			HttpEntity entity = result.getEntity();
//			inpStream = entity.getContent();
		} catch (IOException e) {
			return false;
		}
		
		return true;
	}

	public boolean addVaccine(String pid, String vid) {
		ArrayList<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
//		InputStream inpStream = null; // input stream to parse JSON response
		try {
			HttpClient httpClient = new DefaultHttpClient();
			String addUrl = URL_START + "request=vac&pid=" + pid + "&vid=" + vid;
			HttpPost httpPost = new HttpPost(addUrl.replaceAll("[ ]+", "%20"));
			httpPost.setEntity(new UrlEncodedFormEntity(nvPairs));
			httpClient.execute(httpPost);
//			HttpResponse result = httpClient.execute(httpPost);
//			HttpEntity entity = result.getEntity();
//			inpStream = entity.getContent();
		} catch (IOException e) {
			return false;
		}
		
		return true;
	}
	
	public boolean addVaccineFromOffline(String pid, String vid, String date) {
		ArrayList<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
//		InputStream inpStream = null; // input stream to parse JSON response
		try {
			HttpClient httpClient = new DefaultHttpClient();
			String addUrl = URL_START + "request=vacLocal&pid=" + pid + "&vid=" + vid + "&date=" + date;
			HttpPost httpPost = new HttpPost(addUrl.replaceAll("[ ]+", "%20"));
			httpPost.setEntity(new UrlEncodedFormEntity(nvPairs));
			httpClient.execute(httpPost);
//			HttpResponse result = httpClient.execute(httpPost);
//			HttpEntity entity = result.getEntity();
//			inpStream = entity.getContent();
		} catch (IOException e) {
			return false;
		}
		
		return true;
	}
	
//	public boolean editVaccine(String pid, String vid, String date) {
//		ArrayList<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
//		InputStream inpStream = null; // input stream to parse JSON response
//		try {
//			HttpClient httpClient = new DefaultHttpClient();
//			String addUrl = URL_START + "request=vacLocal&pid=" + pid + "&vid=" + vid + "&date=" + date;
//			HttpPost httpPost = new HttpPost(addUrl.replaceAll("[ ]+", "%20"));
//			httpPost.setEntity(new UrlEncodedFormEntity(nvPairs));
//			HttpResponse result = httpClient.execute(httpPost);
//			HttpEntity entity = result.getEntity();
//			inpStream = entity.getContent();
//		} catch (IOException e) {
//			return false;
//		}
//		
//		return true;
//	}
	
	public Iterator<Patient> getPatientsFromDB() {
		List<Patient> patientList = new ArrayList<Patient>();
		String patientString = httpConn(URL_START + "request=get");
		
		if (patientString == null) {
			return null;
		}
		
		JSONArray jArr;
		try {
			jArr = new JSONArray(patientString);
			JSONObject json_data = null;
			for (int i = 0; i < jArr.length(); i++) {
				json_data = jArr.getJSONObject(i);
				String pid = json_data.get("pid").toString();
				String lname = json_data.get("lname").toString();
				String fname = json_data.get("fname").toString();
				String dob = json_data.get("dob").toString();
				String location = json_data.get("location").toString();
				String fathername = json_data.get("fathername").toString();
				String mothername = json_data.get("mothername").toString();
				String editdate = json_data.get("editdate").toString();
				String conflict = json_data.get("conflict").toString();
				String notes = json_data.get("notes").toString();
				Patient p = new Patient(Integer.parseInt(pid), lname, fname, dob, location, fathername, mothername, editdate, conflict, notes);
				patientList.add(p);
			}
		} catch (JSONException e) {
			return null;
		}

		return patientList.iterator();
	}

	public Set<String[]> getPatientsVaccines(String pid) {
		Set<String[]> vaccines = new HashSet<String[]>();
//		StringBuilder sb = new StringBuilder();
		String patientString = httpConn(URL_START + "request=vacTaken&pid=" + pid);
		if (patientString == null) {
			return null;
		}
		
		JSONArray jArr;
		try {
			jArr = new JSONArray(patientString);
			JSONObject json_data = null;
			for (int i = 0; i < jArr.length(); i++) {
				json_data = jArr.getJSONObject(i);
				String[] info = new String[2];
				info[0] = json_data.get("vid").toString();
				info[1] = json_data.get("dategiven").toString();
				vaccines.add(info);
			}
		} catch (JSONException e) {
			return null;
		}
		
		return vaccines;
	}
	
	public String getEditDate(String pid) {
		String result = null;
		String patientString = httpConn(URL_START + "request=getEditDate&pid=" + pid);
		if (patientString == null) {
			return null;
		}
		
		JSONArray jArr;
		try {
			jArr = new JSONArray(patientString);
			JSONObject json_data = null;
			for (int i = 0; i < jArr.length(); i++) {
				json_data = jArr.getJSONObject(i);
				result = json_data.get("editdate").toString();
			}
		} catch (JSONException e) {
			return null;
		}
		
		return result;
	}
	
	public Iterator<Patient> searchPatientsFromDB(Patient p) {
		int pid = p.id;
		String fname = p.fname;
		String lname = p.lname;
//		String dob = p.dob;
		// TODO: add other fields: location, mothername, fathername, etc
		
		String urlExtra = "request=search";
		if(pid > 0){
			urlExtra += "&pid=" + pid;
		}
		if(fname != ""){
			urlExtra += "&fname=" + fname;
		}
		if(lname != ""){
			urlExtra += "&lname=" + lname;
		}
//		if(dob != ""){
//			urlExtra += "&dob=" + dob;
//		}

		List<Patient> patientList = new ArrayList<Patient>();
		
		String patientString = httpConn(URL_START + urlExtra);
		if (patientString == null) {
			return null;
		}
		
		JSONArray jArr;
		try {
			jArr = new JSONArray(patientString);
			JSONObject json_data = null;
			for (int i = 0; i < jArr.length(); i++) {
				json_data = jArr.getJSONObject(i);
				String pid2 = json_data.get("pid").toString();
				String lname2 = json_data.get("lname").toString();
				String fname2 = json_data.get("fname").toString();
				String dob2 = json_data.get("dob").toString();
				String location2 = json_data.get("location").toString();
				String fathername2 = json_data.get("fathername").toString();
				String mothername2 = json_data.get("mothername").toString();
				String editdate2 = json_data.get("editdate").toString();
				String conflict2 = json_data.get("conflict").toString();
				String notes2 = json_data.get("notes").toString();
				Patient p2 = new Patient(Integer.parseInt(pid2), lname2, fname2, dob2, location2, fathername2, mothername2, editdate2, conflict2, notes2);
				patientList.add(p2);
			}
		} catch (JSONException e) {
			return null;
		}
		
		return patientList.iterator();
	}
	
	public static String httpConn(String url) {
		ArrayList<NameValuePair> nvPairs = new ArrayList<NameValuePair>();
		InputStream inpStream = null; // input stream to parse JSON response
		try {
			HttpClient httpClient = new DefaultHttpClient();
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new UrlEncodedFormEntity(nvPairs));
			HttpResponse result = httpClient.execute(httpPost);
			HttpEntity entity = result.getEntity();
			inpStream = entity.getContent();
		} catch (IOException e) {
			return null;
		}
		
		/* Check if HTTP connection failed */
		if (inpStream == null) {
			return null;
		}
		
		String jsonParse = null;
		/* Build up JSON response from the server */
		try {
			BufferedReader rdr = new BufferedReader(new InputStreamReader(inpStream, "iso-8859-1"), 8);
			StringBuilder sb = new StringBuilder();
			sb.append(rdr.readLine() + "\n");

			String line = "0";
			while ((line = rdr.readLine()) != null) {
				sb.append(line + "\n");
			}
			
			/* Close the input Stream and set the results */
			inpStream.close();
			jsonParse = sb.toString();
		} catch (IOException e) {
			/* Return null immediately on any type of failure */
			return null;
		}
		return jsonParse;
	}
	
	public boolean hasConnection() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        return activeNetwork != null;
    }
	
}

